
// #include <unistd.h>

// #include "Util.hpp"
// #include "LogLevel.hpp"
// #include "Format.hpp"
// #include "LogSink.hpp"
// #include "Logger.hpp"
// #include "LogManager.hpp"
// #include "Log.hpp"

// 以后只需要引用Log.hpp即可
#include "./Log/Log.hpp"


using std::cout;
using std::endl;
//                                                                      TODO 添加 按时间滚动的 落地方案
std::ofstream ofs("./DEUBUG.txt", std::ios::out | std::ios::binary);

void test_util()
{
    std::string str = "./ab/c.txt";
    // auto pos = str.find_last_of("\\/");
    // std::cout << pos << std::endl;
    cout << Log::Util::path(str) << endl;
    cout << Log::Util::isExist(Log::Util::path(str)) << endl;

    cout << Log::Util::createDirectory(Log::Util::path(str)) << endl;
    cout << Log::Util::isExist(Log::Util::path(str)) << endl;

    cout << Log::Util::createDirectory(".") << endl;
}

void test_level()
{
    cout << Log::LogLevel::toString(Log::LogType::UNKNOW) << endl;
    cout << Log::LogLevel::toString(Log::LogType::DEBUG) << endl;
    cout << Log::LogLevel::toString(Log::LogType::WARNING) << endl;
    cout << Log::LogLevel::toString(Log::LogType::ERROR) << endl;
    cout << Log::LogLevel::toString(Log::LogType::FATAL) << endl;
    cout << Log::LogLevel::toString(Log::LogType::OFF) << endl;
}

void test_format()
{
    Log::LogMsg msg(Log::LogType::DEBUG, __FILE__, __LINE__,
                    "logger-H", "socket is closed");

    cout << "--------------------------" << endl;
    Log::Formatter fter("sg{}fsg%d{%H:%M:%S}%Tsdf%t%T[%p]%T[%c]%T%f:%l%T%m%n");
    // [%d{%H:%M:%S}]
    cout << fter.format(msg);

    cout << "--------------------------" << endl;

    fter.ChangePattern("[%d{%H:%M:%S}]%T[%p]%T[%f:%l]%T%m%n");
    fter.AnalysePattern();
    cout << fter.format(msg);

    cout << "--------------------------" << endl;

    fter.ChangePattern("[a{s}dg%%%d{%H:%M:%S}] %m%n");
    fter.AnalysePattern();
    cout << fter.format(msg);

    cout << "--------------------------" << endl;

    fter.ChangePattern("[asdg%%%d{%H:%M:%S}] %m%n{asdf");
    fter.AnalysePattern();
    cout << fter.format(msg);
}

void test_LogSink()
{
    Log::LogMsg msg(Log::LogType::DEBUG, __FILE__, __LINE__,
                    "logger-H", "socket is closed");
    Log::Formatter fter("[%f:%l] %m%n");
    std::string str = fter.format(msg);
    // 标准输入
    Log::LogSink::ptr pstd = Log::LogSinkFactory::create<Log::StdoutLogSink>();
    pstd->log(str.c_str(), str.size());
    std::cout << "-------------------------" << std::endl;
    // 文件
    Log::LogSink::ptr pf = Log::LogSinkFactory::create<Log::FileLogSink>();
    int cnt = 1000;
    while (cnt)
    {
        pf->log(str.c_str(), str.size());
        cnt--;
    }
    std::cout << "-------------------------" << std::endl;
    // // 文件
    Log::LogSink::ptr pf2 = Log::LogSinkFactory::create<Log::FileLogSink>("./Log/logfile.txt");
    cnt = 1000;
    while (cnt)
    {
        pf2->log(str.c_str(), str.size());
        cnt--;
    }
    std::cout << "-------------------------" << std::endl;
    // 滚动文件
    Log::LogSink::ptr prf = Log::LogSinkFactory::create<Log::RollBySizeLogSink>();
    // 写5s
    int i = 0;
    int sz = 1024 * 1024 * 10;
    std::stringstream ss;
    ss << __FILE__ << __LINE__ << "日志调试\n";
    while (i < sz)
    {
        prf->log(ss.str().c_str(), ss.str().size());

        i += ss.str().size();
    }
    std::cout << "-------------------------" << std::endl;
    Log::LogSink::ptr prf2 = Log::LogSinkFactory::create<Log::RollBySizeLogSink>(
        "./Log/RBySz-",
        1024);
    i = 0;
    sz = 1024 * 10;
    while (i < sz)
    {

        prf2->log(ss.str().c_str(), ss.str().size());
        i += ss.str().size();
    }
    std::cout << "-------------------------" << std::endl;
}

// 测试可变参数
void myprintf(const char *fmt, ...)
{
    // vasprintf内部做了格式化参数的提取
    // int vasprintf(char **strp, const char *fmt, va_list ap);
    char *res;
    va_list al;
    va_start(al, fmt);
    int len = vasprintf(&res, fmt, al);
    if (len == -1)
    {
        printf("failed..");
        return;
    }
    std::cout << res << std::endl;
    char buf[32];

    va_list ap;
    va_start(ap, fmt);
    vsnprintf(buf, sizeof(buf), fmt, ap);
    cout << buf << endl;

    va_end(al);
    va_end(ap);
    // 为什么free vasprintf内部做了malloc,需要外部释放
    free(res);
}

void test_logger_sync()
{
    // 1.创建 具体落地方向的数组
    // 原生创建 具体落地对象
    // Log::LogSink::ptr lout(new Log::StdoutLogSink());
    // Log::LogSink::ptr lf(new Log::FileLogSink());
    // Log::LogSink::ptr lrf(new Log::RollBySizeLogSink());

    // 使用工厂模式创建 具体落地对象
    // 函数模板,需要使用<>指名类型,()填充参数
    // Log::LogSink::ptr lout = Log::LogSinkFactory::create<Log::StdoutLogSink>();
    Log::LogSink::ptr lf = Log::LogSinkFactory::create<Log::FileLogSink>();
    Log::LogSink::ptr lrf = Log::LogSinkFactory::create<Log::RollBySizeLogSink>();
    // 使用的是 initializer_list  构造
    std::vector<Log::LogSink::ptr> sinks = {/*lout,*/ lf, lrf};

    // 2. 创建格式转换器
    Log::Formatter::ptr fter(new Log::Formatter("[%d{%H-%M-%S}]%T[%p]%T[%f:%l]%T%m%n"));

    // 3.创建日志器
    Log::Logger::ptr logger = std::make_shared<Log::SyncLogger>(sinks, fter, "Sync_Logger");

    // 4.测试
    int i = 1;
    while (i < 1024)
    {
        logger->debug(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->warn(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->info(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->error(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->fatal(__FILE__, __LINE__, "%s-%d", "日志测试用例", i++);
    }
}

void test_buffer()
{
    // ifstream：读文件,读到内存中来
    std::ifstream ifs;
    ifs.open("./copy.txt", std::ios::in | std::ios::binary);
    if (ifs.is_open() == false)
    {
        std::cout << "ifs.is_open fail " << errno << " " << strerror(errno) << std::endl;
        return;
    }
    ifs.seekg(0, std::ios::end);
    size_t filesz = ifs.tellg();
    ifs.seekg(0, std::ios::beg);
    std::string body;
    body.resize(filesz);
    ifs.read(&body[0], filesz);
    ifs.close();
    // 写到文件中
    Log::Buffer buf;
    int i = 0;
    cout << "filesz = " << filesz << endl;

    for (; i < filesz; i++)
    {
        buf.push(&body[i], 1);
    }

    std::ofstream ofs;
    ofs.open("./copy2.txt", std::ios::out | std::ios::binary);
    int sz = buf.readable();
    for (i = 0; i < sz; i++)
    {
        ofs.write(buf.readBegin(), 1);
        buf.pop(1);
    }
    ofs.close();
    std::cout << errno << " " << strerror(errno) << std::endl;
}

void test_logger_async()
{
    // Log::LogSink::ptr lout = Log::LogSinkFactory::create<Log::StdoutLogSink>();
    Log::LogSink::ptr lf = Log::LogSinkFactory::create<Log::FileLogSink>();
    Log::LogSink::ptr lrf = Log::LogSinkFactory::create<Log::RollBySizeLogSink>();
    // 使用的是 initializer_list  构造
    std::vector<Log::LogSink::ptr> sinks = {/*lout,*/ lf, lrf};
    Log::Formatter::ptr fter(new Log::Formatter("[%d{%H-%M-%S}]%T[%p]%T[%f:%l]%T%m%n"));

    Log::Logger::ptr logger(new Log::AsyncLogger(sinks, Log::AsyncType::ASYNC_SAFE, fter));
    int i = 0;
    int sz = 100;
    while (i < sz)
    {
        logger->debug(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->warn(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->info(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->error(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        logger->fatal(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        i++;
        // std::cout << i << " " << std::endl;
        // sleep(1);
    }
    std::cout << i << " " << std::endl;

    std::cout << errno << " " << strerror(errno) << std::endl;
}

void test_local_builder()
{
    // 多态+继承中,使用基类指针指向派生类
    Log::LoggerBuilder::ptr lp(new Log::LocalLoggerBuilder);
    lp->BuildLoggerType(Log::LoggerType::LOGGER_ASYNC);
    lp->BuildFormatter("%N::[%p][%f:%l] %m%n");
    lp->BuildLimitLevel(Log::LogType::FATAL);
    lp->BuildLoggerName("local-async-logger");
    lp->BuildLoggerSinks<Log::RollBySizeLogSink>("./AsyncLog/RBysz-");
    Log::Logger::ptr async_ptr = lp->Build();

    int i = 0;
    int sz = 100;
    while (i < sz)
    {
        async_ptr->debug(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_ptr->warn(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_ptr->info(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_ptr->error(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_ptr->fatal(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        i++;
        usleep(100);
    }
    // // Log::LoggerBuilder::ptr
    // lp = std::make_shared<Log::LocalLoggerBuilder>();
    lp->BuildLoggerType(Log::LoggerType::LOGGER_SYNC);
    lp->BuildFormatter("%N::[%p][%f:%l] %m%n");
    lp->BuildLimitLevel(Log::LogType::ERROR);
    lp->BuildLoggerName("local-sync-logger");
    lp->BuildLoggerSinks<Log::RollBySizeLogSink>("./SyncLog/RBysz-");
    Log::Logger::ptr sync_ptr = lp->Build();
    i = 0;
    while (i < sz)
    {
        sync_ptr->debug(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        sync_ptr->warn(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        sync_ptr->info(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        sync_ptr->error(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        sync_ptr->fatal(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        i++;
        usleep(100);
    }
}

void global_log()
{
    Log::Logger::ptr async_logger = Log::LogManager::GetInstance().GetLogger("global-async-logger");
    int i = 0;
    int sz = 100;
    while (i < sz)
    {
        async_logger->debug(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_logger->warn(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_logger->info(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_logger->error(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        async_logger->fatal(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        i++;
        usleep(100);
    }
}

void test_globalbuilder_LoggerManager()
{
    Log::Logger::ptr root_logger = Log::LogManager::GetInstance().GetRootLogger();
    int i = 0;
    int sz = 10;
    while (i < sz)
    {
        root_logger->debug(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        root_logger->warn(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        root_logger->info(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        root_logger->error(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        root_logger->fatal(__FILE__, __LINE__, "%s-%d", "日志测试用例", i);
        i++;
    }
    std::cout << "-------------------------" << std::endl;
    Log::LoggerBuilder::ptr lp(new Log::GlobalLoggerBuilder);
    lp->BuildLoggerType(Log::LoggerType::LOGGER_ASYNC);
    lp->BuildFormatter("%N::[%p][%f:%l] %m%n");
    lp->BuildLimitLevel(Log::LogType::FATAL);
    lp->BuildLoggerName("global-async-logger");
    lp->BuildLoggerSinks<Log::RollBySizeLogSink>("./AsyncLog/RBysz-");
    lp->Build();
    global_log();
}

void define_agent(std::string name)
{
    // 获取日志器
    Log::Logger::ptr lg = Log::GetLogger(name);
    int i = 0;
    int sz = 100;
    // lg->debug();
    while (i < sz)
    {
        lg->debug("%s-%d", "debug", i);
        lg->warn("%s-%d", "warn", i);
        lg->info("%s-%d", "info", i);
        lg->error("%s-%d", "error", i);
        lg->fatal("%s-%d", "fatal", i);

        LOG_DEBUG(lg,"%s-%d","日志测试用例",i);
        LOG_WARN(lg,"%s-%d","日志测试用例",i);
        LOG_INFO(lg,"%s-%d","日志测试用例",i);
        LOG_ERROR(lg,"%s-%d","日志测试用例",i);
        LOG_FATAL(lg,"%s-%d","日志测试用例",i);
        i++;
        usleep(100);
    }

    i = 0;
    while (i < sz)
    {
        DF_DEBUG("%s-%d","DF_DEBUG",i);
        DF_WARN("%s-%d","DF_WARN",i);
        DF_INFO("%s-%d","DF_INFO",i);
        DF_ERROR("%s-%d","DF_ERROR",i);
        DF_FATAL("%s-%d","DF_FATAL",i);

        D_DEBUG("%s-%d","D_DEBUG",i);
        D_WARN("%s-%d","D_WARN",i);
        D_INFO("%s-%d","D_INFO",i);
        D_ERROR("%s-%d","D_ERROR",i);
        D_FATAL("%s-%d","D_FATAL",i);
        i++;
    }
}

void test_define_agent()
{
    Log::LoggerBuilder::ptr lp(new Log::GlobalLoggerBuilder);
    lp->BuildLoggerType(Log::LoggerType::LOGGER_ASYNC);
    lp->BuildFormatter("%N::[%p][%f:%l] %m%n");
    lp->BuildLimitLevel(Log::LogType::FATAL);
    lp->BuildLoggerName("global-async-logger");
    lp->BuildLoggerSinks<Log::RollBySizeLogSink>("./AsyncLog/RBysz-");
    lp->Build();
    define_agent("global-async-logger");
}
void test()
{
    if (ofs.is_open() == false)
    {
        std::cout << "ofs failed" << std::endl;
        return;
    }
    // test_util();
    // test_level();
    // test_format();
    // test_LogSink();
    // myprintf("%s-%d", "⼩明", 18);
    // test_logger_sync();
    // test_buffer();
    // test_logger_async();
    // test_local_builder();
    // test_globalbuilder_LoggerManager();
    test_define_agent();

    ofs.close();
}

int main()
{
    test();
    return 0;
}